
import java.util.Scanner;
import java.util.StringTokenizer;

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */



/**
 *
 * @author Alejo
 */
public class MainLispTLR {
    
    static int numeroDeLinea=1;
    static String lineaingresada;
    static boolean salirlisp;
    static boolean norevisar;
    static Lista lineaingre;
    static String atomo;
    
    /**
     * @param args 
     */
    public static void main(String[] args) {
        // TODO code application logic here
        salirlisp = false;
        logolisp();
        
        do {
        norevisar = false;
        Scanner ingreso = new Scanner (System.in);
	
        System.out.print("["+numeroDeLinea+"]> ");
        lineaingresada = "";
        lineaingresada += ingreso.nextLine().replace('\n', ' '); 
        lineaingresada=ingresoinstrucciones(lineaingresada);
        if ((lineaingresada.compareToIgnoreCase("exit")== 0)){
        salirlisp = true;
        norevisar = true;
        }
        if ((lineaingresada.compareToIgnoreCase("")== 0)){
        norevisar = true;
        } 
         if (!(norevisar)){
             lineaingre= generadorLista(lineaingresada);
         }
        
        System.out.println(lineaingresada);
        }while(!salirlisp);
        
        
    }
    
    /**
     * Procedimiento que genera lista de atomos referente a una expresion ingresada como comando para el interprete
     * @param lineaingresada1 texto del cual se desea generar la lista formada por los atomos de l expresion
     * @return Devuelve una lista con los atomos de una expresion ingresada
     */
    public static Lista generadorLista(String lineaingresada1){
        boolean eliminarpar = false;
        Lista lineaingre1 = new Lista();
        System.out.println(lineaingresada1);
        for (int i =lineaingresada1.length()-1; i > 0 ; i --){
                 if ((lineaingresada1.charAt(i)+"").compareTo(")") == 0) {
                 lineaingresada1 = lineaingresada1.substring(1, i);
                // System.out.println("si hizo cmabio "+ lineaingresada.charAt(i)+"");
                 eliminarpar = true;
                 break;
                }
                 
             }
        if (!(eliminarpar)){
            lineaingresada1 = lineaingresada1.replace('(',' ');
            eliminarpar = false;
        }
             lineaingre1 = new Lista();
             Lista listtemp = new Lista();
         StringTokenizer separar = new StringTokenizer(lineaingresada1);
          Atoms atomtemp = new Atoms();
        while (separar.hasMoreTokens()) {
                 
                    atomo =  separar.nextToken();
                    System.out.println(atomo);
                    if(((atomo.charAt(0)+"").compareTo("(")== 0)){
                      if(((atomo.length())== 2)) {
                        listtemp.agregar(new Atoms((atomo.charAt(1)+"")));
                      }
                     
                      if (((atomo.length())> 2)){
                                 
                       atomtemp=( new Atoms (generadorLista(atomo)));
                      listtemp.agregar(atomtemp);
                       System.out.println("Cuando sale de caso simple");
                      }
                        
                        
                        
                       // System.out.println(listtemp.getAtomo(2));
                    }
                    else{atomtemp = new Atoms(atomo);
                    }
                  
                 // System.out.println(atomtemp);
                 
                  
                  lineaingre1.agregar(atomtemp);
	         System.out.println(lineaingre1);
	     } 
    return lineaingre1;
    }
    /**
     * Procedimiento que permite generar una lista para generar un atomo de la lista generada
     * @param separar es un StringTokenizer de cual se obtienen los String para generar atoms
     * @return Una lista para generar un atomo a partir de la lista ingresada
     */
    public static Lista listaparaatomo(StringTokenizer separar){
                            boolean finlistaint = true;
                            Lista listtemp1 = new Lista();
                            while (finlistaint){
                            
                            //System.out.println(atomo);
                            if(((atomo.length()) > 2)) {
                                if ((((atomo.charAt(atomo.length() -1)+"").compareTo(")")== 0))){
                                     atomo =  (atomo.charAt(0)+"");
                                     listtemp1.agregar(new Atoms(atomo));
                                    // System.out.println(listtemp + " 1");
                                     finlistaint = false;
                                }
                                else{
                                atomo =  separar.nextToken();
                                listtemp1.agregar(new Atoms(atomo));
                                //System.out.println(listtemp +" 2");
                                atomo = separar.nextToken();
                                //System.out.println("Else 1");
                                    }
                            }
                            else{
                               
                               listtemp1.agregar(new Atoms(atomo));
                               atomo =  separar.nextToken();
                               //System.out.println(listtemp+" 3");
                               //System.out.println("Else 2");
                                
                            }
                        }return listtemp1;
    
    }
    
    /**
     * Procedimiento que  evalua la sintaxis de una expresion ingresada, y de ser correcta devuelve la misma espresion ingresada de lo contrario 
     * sera una cada en blanco.
     * @param lineaingresada Lista a evular si cumple con la sitaxis minima de una expresion lisp
     * @return Si la expresion ingresada es correcta con respecto sintaxis, se devuelve la expresion ingresada de lo contrario se devuelve un string en blanco
     */
    public static String ingresoinstrucciones (String lineaingresada){
        
        int numeroparentesis = 0;
            if(contarCaracter('(',lineaingresada)==0){         
                if(contarCaracter(')',lineaingresada)!=0){
                 System.out.println("Error no hay la misma cantidad de parentesis abiertos como cerrados ");
                lineaingresada = "";                                
                }
            }
            numeroparentesis =  contarCaracter('(',lineaingresada);
            numeroparentesis -= contarCaracter(')',lineaingresada);
            if (!(numeroparentesis == 0)) {System.out.println("Error no hay la misma cantidad de parentesis abiertos como cerrados ");
                  lineaingresada = "";  
            }     
            if (lineaingresada.compareToIgnoreCase("(exit)") == 0){
               lineaingresada = "exit";
            }
        numeroDeLinea ++;
        return lineaingresada;
    
    }
    
   

    
    
    /**
     * Procedimiento que permite contar la ocurrencias de un caracter en una cadena.
     * @param caracter es el parametro que se desea buscar y contar en la cadena de caracteres
     * @param ingreso cadena de caracteres en la cual se desea buscar un caracter determinado y contar sus ocurrencias
     * @return
     */
    public static int contarCaracter(char caracter, String ingreso) {
		int contador = 0;
		for (int i = 0 ; i < ingreso.length() ; i++){
			if (ingreso.charAt(i)==caracter)
				contador++;
                                            }
		return contador;
	}
    
   /**
    * Metodo que imprime el logo de Lips realizado por el grupo.
    */
   public static void logolisp(){
   
    System.out.println(             "***********************************************************************************************" +
				   	"\n------------------------------------------------------------------------------------------\n " +
				   	"\n .MMMMM        ..MMM.                             TTTTTTTTTTTT LLLLL       RRRRRRRRRR        " +     
				   	"\n .MMMMM        . MMM     .  .          .. .       TTTTTTTTTTTT LLLLL       RRRRRRRRRRRR      " +  
				   	"\n .MMMMM         MMMMM  .. MMMMM..  MMMMMMMMM$.       TTTTTT    LLLLL       RRRRR    RRRR     " +   
				   	"\n .MMMMM         MMMMM  .MMMMMMMM   MMMMMMMMMMMM      TTTTTT    LLLLL       RRRRR    RRRRR    " +  
				   	"\n .MMMMM         MMMMM  7MMMM ....  MMMMM..MMMMM$     TTTTTT    LLLLL       RRRRR    RRRRR    " +
				   	"\n .MMMMM         MMMMM  .MMMMMMMI   MMMMM.  MMMMM     TTTTTT    LLLLL       RRRRR    RRRR     " +
				   	"\n .MMMMM      .  MMMMM   .  MMMMMM  MMMMM...MMMMM.    TTTTTT    LLLLL       RRRRRRRRRRRR      " +
				   	"\n .MMMMMMMMMMMM  MMMMM  .MMMMMMMMM  MMMMMMMMMMMM      TTTTTT    LLLLLLLLLL  RRRRR   RRR       " +
				   	"\n  MMMMMMMMMMMM  MMMMM  .MMMMMMMM   MMMMMMMMMMM       TTTTTT    LLLLLLLLLL  RRRRR   RRRR      " +
				   	"\n  .            .     .   ...       MMMMM   .                               RRRRR   RRRRR     " +
				   	"\n                                   MMMMM.                                  RRRRR   RRRRRR    " +
				   	"\n                                   MMMMM.                                                    " +
				   	"\n\nEn Interprete Common Lisp Martha Thomae, Chritopher Luttmann, Alejandro Rojas (UVG, 20011) " +
				   	"\n Para m‡s informaci—n, visite http://code.google.com/p/proyecto3lisp/source/browse/         " +
				   	"\n---------------------------------------------------------------------------------------------" +
					"\n**********************************************************************************************\n");
   }
    
}
